package project.svc.generic;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Map;

import online.model.UniModel;
import online.model.UniModelImpl;
import project.base.QueryAbstract;
import common.db.JdbcSource;
import common.db.jdbc.Jdbc;
import common.sql.QueryUtil;
import common.sql.SelectQuery;
import common.sql.Selector;
import core.config.Factory;

/**
 * クエリサービス
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class QueryService extends QueryAbstract implements SelectQuery {

	/** クエリファイル */
	private String query = null;
	/** 汎用モデル（条件） */
	private UniModel param = null;
	/** 汎用モデル（結果） */
	private UniModel model = new UniModelImpl();

	/**
	 * クエリファイル設定
	 * @param val クエリファイル
	 */
	public void setQueryFile(final String val) {
		this.query = val;
	}

	/**
	 * 汎用モデル設定
	 * @param val 汎用モデル
	 */
	public void setUniModel(final UniModel val) {
		this.param = new UniModelImpl(val);
	}

	/**
	 * 汎用モデル取得
	 * @return 汎用モデル
	 */
	public UniModel getResultModel() {
		return this.model;
	}

	/**
	 * @see common.sql.SelectQuery#callback(java.sql.ResultSet)
	 */
	@Override
	public boolean callback(final ResultSet rs) throws SQLException {
		this.model.putAll(super.initModel(rs));

		boolean ret = false;
		ResultSetMetaData rsmd = rs.getMetaData();
		while (rs.next()) {
			ret = true;
			for (int i = 1; i <= rsmd.getColumnCount(); i++) {
				super.addValue(this.model, rs, i);
			}
		}
		return ret;
	}

	/**
	 * @see common.sql.SelectQuery#makeParam()
	 */
	@Override
	public Map<String, Object> makeParam() {
		return super.toParamMap(this.param);
	}

	/**
	 * @see common.sql.SelectQuery#makeQuery()
	 */
	@Override
	public String makeQuery() {
		return QueryUtil.getSqlFromFile(this.query);
	}

	/**
	 * 検索処理
	 * @return レコードが存在した場合 true を返す。
	 */
	public boolean search() {
		try (Jdbc conn = JdbcSource.getConnection(super.getSchema())) {
			Selector sc = Factory.create(Selector.class);
			sc.setConnection(conn);
			return sc.search(this);
		}
	}

	/**
	 * 存在確認処理
	 * @return レコードが存在した場合 true を返す。
	 */
	public boolean exist() {
		try (Jdbc conn = JdbcSource.getConnection(super.getSchema())) {
			Selector sc = Factory.create(Selector.class);
			sc.setConnection(conn);
			sc.setFetchSize(1);
			sc.setMaxRows(1);
			return sc.search(this);
		}
	}
}
